﻿#include "DeMuxerAndPlayWindow.h"
#include <QFileDialog>
#include <QSize>
#include <QMessageBox>
#include <Qt>
extern"C"
{
#include "libavformat/avformat.h"
#include "libavcodec/avcodec.h"
#include "libavutil/avutil.h"
}

void PrintErr(int err)
{
	char buf[1024] = { 0 };
	av_strerror(err, buf, sizeof(buf) - 1);
	qDebug() << buf << endl;
}


DeMuxerAndPlayWindow::DeMuxerAndPlayWindow(QWidget* parent)
	: QWidget(parent)
{
	ui.setupUi(this);
	this->setWindowTitle("解封装后解码渲染");
	setAttribute(Qt::WA_DeleteOnClose, true);  // 关闭时自动销毁窗口
}

void DeMuxerAndPlayWindow::onSelectedFile()
{
	QString filter = "所有文件(*.*)"; //文件过滤器
	QString filePath = QFileDialog::getOpenFileName(this, "选择文件", "", filter);
	this->fileName = filePath;
	this->ui.outputPathEdit->setText(this->fileName);
}

void DeMuxerAndPlayWindow::onStartPlay()
{
	isRunning = true;
	if (this->fileName.isEmpty()) {
		QMessageBox::information(this, "温馨提示", "参数不对请检查参数");
		return;
	}
	connect(this, &DeMuxerAndPlayWindow::updateSize, this, &DeMuxerAndPlayWindow::onUpdateSize, Qt::QueuedConnection);
	isRunning = true;
	renderThread = std::make_unique<std::thread>(&DeMuxerAndPlayWindow::OnDraw, this);

}

/// <summary>
/// 接收子线程发送过来的信号，更新槽函数，此处主要更新的是UI
/// </summary>
/// <param name="videoWidth">视频宽度</param>
/// <param name="videoHeight">视频高度</param>
void DeMuxerAndPlayWindow::onUpdateSize(int videoWidth, int videoHeight)
{
	ui.labelVideo->move(0, 0);
	ui.labelVideo->resize(QSize(videoWidth, videoHeight));
	resize(QSize(videoWidth, videoHeight));
	renderView = IVideoRenderView::Create();
	renderView->Init(videoWidth, videoHeight, IVideoRenderView::YUV420P, (void*)ui.labelVideo->winId());
}

void DeMuxerAndPlayWindow::OnDraw()
{
	//打开文件流
	AVFormatContext* ic = nullptr;
	int ret = avformat_open_input(&ic, this->fileName.toStdString().c_str(),
		NULL,//封装器格式 null 自动探测 根据后缀名或者文件头
		NULL);//参数设置，rtsp需要设置
	if (ret != 0)
	{
		qDebug() << "avformat_open_input failed！打开解封装上下文失败";
		return;
	}

	//发现媒体流信息
	ret = avformat_find_stream_info(ic, NULL);
	if (ret < 0)
	{
		qDebug() << "avformat_find_stream_info failed!";
		return;
	}

	//找到音视频流
	AVStream* vs = nullptr;
	AVStream* as = nullptr;
	for (int i = 0;i < ic->nb_streams;i++)
	{
		//视频
		if (ic->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
		{
			vs = ic->streams[i];
		}
		else if (ic->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)//音频
		{
			as = ic->streams[i];
		}
	}

	int videoWidth = vs->codecpar->width;
	int videoHeight = vs->codecpar->height;
	emit updateSize(videoWidth, videoHeight);//发送信号到槽函数


	//创建一个解码器
	YDecoder* decoder = new YDecoder();
	AVCodecContext* context = decoder->Create(vs->codecpar->codec_id, false);
	//解封装的视频编码参数，传递给解码上下文
	avcodec_parameters_to_context(context, vs->codecpar);
	decoder->setContext(context);
	decoder->Open();


	//解封装
	AVPacket pkt;
	auto* frame = av_frame_alloc();
	//auto frame = decoder->CreateFrame();
	while (isRunning)
	{
		ret = av_read_frame(ic, &pkt);
		if (ret != 0)
		{
			qDebug() << "解码结束";
			PrintErr(ret);
			break;
		}
		if (vs && pkt.stream_index == vs->index)
		{
			if (!decoder->Send(&pkt))break;
			while (decoder->Receive(frame))
			{
				renderView->DrawFrame(frame);
				std::this_thread::sleep_for(std::chrono::milliseconds(1000 / 25));
			}
			qDebug() << "视频,width=" << vs->codecpar->width << ",height=" << vs->codecpar->height;
		}
		else if (as && pkt.stream_index == as->index)
		{
			qDebug() << "音频";
		}

		av_packet_unref(&pkt);//引用计数减一
	}
	avformat_close_input(&ic);
}

void DeMuxerAndPlayWindow::closeEvent(QCloseEvent* event) {
	event->accept();  // 接受关闭事件（允许关闭）
	if (isRunning)
	{
		isRunning = false;
		if (renderThread && renderThread->joinable())
		{
			renderThread->join();
		}
		if (renderView)
		{
			renderView->Close();
			renderView = nullptr;
		}
	}

	qDebug() << "窗口已关闭";
}

DeMuxerAndPlayWindow::~DeMuxerAndPlayWindow()
{
}
